/*
Filename:    circular_buffer_const_iterator.h
Author:      Erik Öjebo
Date:        2009-01-10
Description: Iterator class for the generic circular buffer class
             CircularBuffer.
Note:        The iterator is a const iterator, so the data accessed through
             the iterator cannot be modified.
             The implementation is in the header file to avoid problems,
             since the class is generic.
*/

#ifndef CIRCULAR_BUFFER_CONST_ITERATOR_H_
#define CIRCULAR_BUFFER_CONST_ITERATOR_H_

template <class T> class CircularBuffer;

template <class T>
class CircularBufferConstIterator
{
public:
    // Creates a new iterator, pointing to the first element in the buffer
    CircularBufferConstIterator(CircularBuffer<T> const * buffer);

    // Moves the iterator to the next element in the buffer
    void operator++(int i);

    // Checks if the iterator has reached the end of the buffer
    bool isAtEnd() const;

    // Returns the data of the current buffer element
    const T& data() const;

private:
    CircularBuffer<T> const * buffer;
    bool isAtEndOfBuffer;
    int currentIndex;
};

// IMPLEMENTATION

template<class T>
CircularBufferConstIterator<T>::
    CircularBufferConstIterator(CircularBuffer<T> const * buffer)
        : buffer(buffer), isAtEndOfBuffer(false)
{
    // Point the new iterator to the oldest index in the buffer:
    this->currentIndex = buffer->getOldestIndex();
}

template<class T>
void CircularBufferConstIterator<T>::operator++(int i)
{
    // Only move the iterator forward if it is not already at the end:
    if (!isAtEndOfBuffer)
    {
        // If moving one step forward would mean going back to the oldest
        // element in the buffer the end of the buffer is reached.
        int nextIndex = buffer->getNextIndex(currentIndex);
        if (nextIndex == buffer->getOldestIndex())
            isAtEndOfBuffer = true;
        else
            currentIndex = nextIndex;
    }
}

template<class T>
bool CircularBufferConstIterator<T>::isAtEnd() const
{
    return isAtEndOfBuffer;
}

template<class T>
const T& CircularBufferConstIterator<T>::data() const
{
    // Return the element that the iterator currently points at.
    return buffer->data(currentIndex);
}



#endif /* CIRCULAR_BUFFER_CONST_ITERATOR_H_ */
